package cn.iocoder.yudao.framework.datasource.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 雪花算法工具类
 *
 * @className: SnowIdUtil
 * @author: tangkh
 * @date: 2023-09-19 16:41
 */
public class SnowIdUtil {
    private static final Logger log = LoggerFactory.getLogger(SnowIdUtil.class);
    public static int DATA_CENTER_BIT = 5;
    public static int WORKER_BIT = 5;
    public static int SEQ_BIT = 12;
    public static long EPOCH = 1288834974657L;

    public SnowIdUtil() {
    }

    public static long datetimeBySnowId(long snowId) {
        try {
            String bid = Long.toBinaryString(snowId);
            int timestamp = bid.length() - (WORKER_BIT + DATA_CENTER_BIT + SEQ_BIT);
            String substring = bid.substring(0, timestamp);
            return Long.parseUnsignedLong(substring, 2) + EPOCH;
        } catch (Exception var5) {
            log.warn("this id is not a snowId : {} ", snowId);
            return 0L;
        }
    }

    public static List<Long> noSnowIds(List<Long> snowIds) {
        return (List)snowIds.stream().filter((sn) -> {
            return datetimeBySnowId(sn) == 0L;
        }).collect(Collectors.toList());
    }

    public static Pair<Date, List<Long>> minDateNoSnowIds(List<Long> ids) {
        List<Long> snowIds = ids.stream().filter((sn) -> datetimeBySnowId(sn) > 0L && sn.toString().length() >= 18).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(snowIds)) {
            return Pair.of(null, ids);
        } else {
            long l = datetimeBySnowId((snowIds.stream().sorted(Long::compareTo).collect(Collectors.toList())).get(0));
            List<Long> snowList = new ArrayList<>(snowIds);
            List<Long> idList = new ArrayList<>(ids);
            idList.removeAll(snowList);
            return Pair.of(new Date(l), idList);
        }
    }
}
